package com.ruoyi.common.utils;


import cn.hutool.core.util.RandomUtil;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.model.CannedAccessControlList;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.region.Region;
import com.ruoyi.common.entity.StorageConfig;
import com.ruoyi.common.service.StorageConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.UUID;

/**
 * 腾讯云COS上传工具类（从数据库动态获取配置）
 * @author 0617
 */
@Slf4j
@Component
public class TencentOssUploadUtils {

    @Autowired
    private StorageConfigService storageConfigService;

    /**
     * 上传文件到腾讯云COS
     * @param file 待上传文件
     * @return 文件访问URL
     * @throws Exception 上传异常
     */
    public String uploadFile(MultipartFile file) throws Exception {
        // 1. 从数据库获取腾讯云配置（storage_type为'tencent'）
        StorageConfig tencentConfig = storageConfigService.getByStorageType("tencent");
        if (tencentConfig == null) {
            throw new RuntimeException("未配置腾讯云COS信息，请先在系统中配置");
        }

        // 2. 初始化COS客户端
        COSClient cosClient = initCos(tencentConfig);

        try {
            // 3. 生成UUID文件名（保持原文件扩展名）
            String originalFilename = file.getOriginalFilename();
            String fileType = originalFilename.substring(originalFilename.lastIndexOf("."));
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            String fileName = uuid + fileType;

            // 4. 构建文件存储路径（可自定义前缀）
            String filePath = getFilePath(fileName);

            // 5. 准备文件上传流
            InputStream inputStream = file.getInputStream();

            // 6. 设置上传文件元数据
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(file.getSize());

            // 7. 构建上传请求
            PutObjectRequest putObjectRequest = new PutObjectRequest(
                    tencentConfig.getBucketName(),  // 存储桶名称
                    filePath,                       // 存储路径+文件名
                    inputStream,                    // 文件流
                    objectMetadata                  // 元数据
            );

            // 8. 执行上传
            cosClient.putObject(putObjectRequest);

            // 9. 设置文件访问权限为公共读
            cosClient.setBucketAcl(tencentConfig.getBucketName(), CannedAccessControlList.PublicRead);

            // 10. 构建并返回访问URL
            String baseUrl = tencentConfig.getDomain();  // 从配置获取域名（如：https://xxx-1251234567.cos.ap-beijing.myqcloud.com）
            return baseUrl + "/" + filePath;

        } catch (Exception e) {
            log.error("腾讯云COS上传失败", e);
            throw new RuntimeException("文件上传失败：" + e.getMessage());
        } finally {
            // 11. 关闭客户端
            if (cosClient != null) {
                cosClient.shutdown();
            }
        }
    }

    /**
     * 构建文件存储路径
     * @param fileName 文件名
     * @return 完整存储路径
     */
    private String getFilePath(String fileName) {
        // 可根据需求调整路径格式，如添加日期目录
        return "upload/" + fileName;  // 示例：upload/xxx.jpg
    }

    /**
     * 初始化COS客户端
     * @param config 腾讯云配置
     * @return COSClient实例
     */
    private COSClient initCos(StorageConfig config) {
        // 1. 验证必要配置
        if (config.getSecretKey() == null || config.getAccessKey() == null
                || config.getRegion() == null || config.getBucketName() == null) {
            throw new RuntimeException("腾讯云COS配置不完整，请检查密钥、区域和存储桶信息");
        }

        // 2. 初始化身份信息
        BasicCOSCredentials credentials = new BasicCOSCredentials(
                config.getAccessKey(),   // SecretId（对应实体类的accessKey字段）
                config.getSecretKey()    // SecretKey
        );

        // 3. 设置区域
        Region region = new Region(config.getRegion());  // 如：ap-beijing
        ClientConfig clientConfig = new ClientConfig(region);

        // 4. 返回客户端实例
        return new COSClient(credentials, clientConfig);
    }
}
